package com.ht.module.sys.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ht.constant.RedisConstants;
import com.ht.module.sys.entity.SysDict;
import com.ht.module.sys.entity.SysDictItem;
import com.ht.module.sys.mapper.SysDictItemMapper;
import com.ht.module.sys.mapper.SysDictMapper;
import com.ht.module.sys.service.ISysDictItemService;
import com.ht.module.sys.service.ISysDictService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ht.util.CommMethod;
import com.ht.util.Pager;
import com.ht.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 字典表 服务实现类
 * </p>
 *
 * @author Auto-generator
 * @since 2021-05-19
 */
@Service
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements ISysDictService {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysDictItemService sysDictItemService;

    @Override
    public Pager<SysDict> findPage(Pager<SysDict> pager, SysDict sysDict) {
        QueryWrapper<SysDict> qw = new QueryWrapper<>();
        if (StrUtil.isNotEmpty(sysDict.getDictName())) {
            qw.like("dict_name", sysDict.getDictName());
        }
        if (StrUtil.isNotEmpty(sysDict.getDictCode())) {
            qw.like("dict_code", sysDict.getDictCode());
        }
        return baseMapper.selectPage(pager, qw);
    }

    @Override
    public List<SysDictItem> getItem(String code) {
        //先从redis中获取码表值
        Map<String, List<SysDictItem>> map = (Map<String, List<SysDictItem>>) redisUtil.get(RedisConstants.DICT_LIST);
        if (ObjectUtil.isEmpty(map)) {
            //全量同步
            return this.fullCacheRedis(code);
        }
        if (ObjectUtil.isEmpty(map.get(code))) {
            //增量同步
            List<SysDictItem> sysDictItems = this.addCacheRedis(map, code);
            return sysDictItems;
        }
        return map.get(code);
    }

    /**
     * 全量同步
     */
    public void fullCacheRedis() {
        //如果map不存在在全量同步-查询出所有码表
        List<SysDict> sysDicts = baseMapper.selectList(new QueryWrapper<>());
        //查询出所有字典项
        List<SysDictItem> sysDictItems = sysDictItemService.findList(new SysDictItem());
        //定义缓存map对象
        Map<String, List<SysDictItem>> map = new HashMap<>();
        for (SysDict sysDict : sysDicts) {
            //遍历字典
            map.put(sysDict.getDictCode(), sysDictItems.stream().filter(x -> x.getDictId().equals(sysDict.getId())).collect(Collectors.toList()));
        }
        //存入缓存
        redisUtil.set(RedisConstants.DICT_LIST, map);
    }

    /**
     * 全量同步并返回code的字典项
     */
    private List<SysDictItem> fullCacheRedis(String code) {
        //如果map不存在在全量同步-查询出所有码表
        List<SysDict> sysDicts = baseMapper.selectList(new QueryWrapper<>());
        //查询出所有字典项
        List<SysDictItem> sysDictItems = sysDictItemService.findList(new SysDictItem());
        //定义缓存map对象
        Map<String, List<SysDictItem>> map = new HashMap<>();
        for (SysDict sysDict : sysDicts) {
            //遍历字典
            map.put(sysDict.getDictCode(), sysDictItems.stream().filter(x -> x.getDictId().equals(sysDict.getId())).collect(Collectors.toList()));
        }
        //存入缓存
        redisUtil.set(RedisConstants.DICT_LIST, map);

        //找到当前编码的字典
        List<SysDict> temp=sysDicts.stream().filter(x->x.getDictCode().equals(code)).collect(Collectors.toList());
        if(temp.size()==0){
            return null;
        }
        return  sysDictItems.stream().filter(x -> x.getDictId().equals(temp.get(0).getId())).collect(Collectors.toList());
    }

    /**
     * 按字典编码增量同步
     */
    @Override
    public List<SysDictItem> addCacheRedis(Map<String, List<SysDictItem>> map, String code) {
        //查询出码表的值
        List<SysDictItem> items = baseMapper.getItem(code);
        //判断码表是否存在
        if(items.size()>0){
            map.put(code,items);
            redisUtil.set(RedisConstants.DICT_LIST, map);
        }
        return items;
    }

    @Override
    @Transactional
    public void edit(SysDict sysDict) {
        CommMethod.beanUpdate(sysDict);
        //查询之前的key
        SysDict temp = baseMapper.selectById(sysDict.getId());
        //修改数据库的值
        baseMapper.updateById(sysDict);

        //判断是否需要同步缓存
        if(!StrUtil.equals(temp.getDictCode(),sysDict.getDictCode())){
            //获取缓存中的值
            Map<String, List<SysDictItem>> map = (Map<String, List<SysDictItem>>) redisUtil.get(RedisConstants.DICT_LIST);
            //删除旧的缓存
            map.remove(temp.getDictCode());
            //增量同步
            addCacheRedis(map,sysDict.getDictCode());
        }
    }

    @Override
    @Transactional
    public void delById(String id) {
        //查询出当前字典
        SysDict temp = baseMapper.selectById(id);
        //删除字典表
        baseMapper.deleteById(id);
        //删除字典项
        sysDictItemService.remove(new QueryWrapper<SysDictItem>().eq("dict_id",id));
        //删除缓存
        //获取缓存中的值
        Map<String, List<SysDictItem>> map = (Map<String, List<SysDictItem>>) redisUtil.get(RedisConstants.DICT_LIST);
        //删除旧的缓存
        map.remove(temp.getDictCode());
        //同步
        redisUtil.set(RedisConstants.DICT_LIST, map);
    }


}
